package com.sky.chapter3.cas;

import java.util.ArrayList;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicLong;

/**
 * @author : wushikai
 * <p>
 * date : 2022-07-05
 */
class CasDemo1 {


    private volatile static int number = 0;

    //读取
    public int getNumber() {
        return number;
    }

    //使用 synchronized 保证原子性
    private static synchronized void safeSetNumber() {
        number++;
    }

    /*cas 类 */
    private static AtomicLong atomicNumber = new AtomicLong(0);

    public static long getAtomicNumber() {
        return atomicNumber.get();
    }

    /*使用 cas 保证原子性*/
    private static void setAtomicNumber() {
        CasDemo1.atomicNumber.incrementAndGet();
    }

    /**
     * 不保证原子性
     */
    private static void setNumber() {
        number++;
    }


    /**
     * 设置组合
     * 非cas类 和 cas类组合 是否线程安全
     */
    private static void setCombine() {
        number++;
        CasDemo1.atomicNumber.incrementAndGet();
    }


    /**
     * 测试  线程 错误
     * <p>
     * number = 298942
     * atomicNumber = 300000
     * cas的数值正确,  非cas 的 数值错误;
     */
    private static void noUseCas() throws InterruptedException {

        ExecutorService executorService = Executors.newFixedThreadPool(3000);

        ArrayList<Callable<Integer>> futureTasks = new ArrayList<>();
        for (int i = 0; i < 300000; i++) {  //30000 可能不够, 数值越高, 结果越明显;

            futureTasks.add(() -> {
                setCombine();
                return null;
            });
        }
        executorService.invokeAll(futureTasks);
        executorService.shutdown();

        Thread.sleep(3000);
        System.out.println("number = " + number);
        System.out.println("atomicNumber = " + atomicNumber.get());
    }


    /*测试 cas */
    private static void useCas() throws InterruptedException {

        ExecutorService executorService = Executors.newFixedThreadPool(3000);

        ArrayList<Callable<Integer>> futureTasks = new ArrayList<>();
        for (int i = 0; i < 300000; i++) {  //30000 可能不够, 数值越高, 结果越明显;

            futureTasks.add(() -> {
                setAtomicNumber();
                return null;
            });
        }
        executorService.invokeAll(futureTasks);
        executorService.shutdown();

        Thread.sleep(1000);
        System.out.println("atomicNumber = " + atomicNumber.get());

    }


    public static void main(String[] args) throws InterruptedException {
        noUseCas();
        //useCas();


    }


}

